/*
  泛型变量，泛型类
    为什么要有泛型：
      泛型就是为了解决、类、接口、方法的复用性，以及对不特定数据类型的支持，同时还保障原有的类型校验
*/

// 例： 在过去由于数据类型不同，会造成代码的冗余

function getInfo(value: number): number {
  return value
}

function getInfos(value: string): string {
  return value
}
function getinfob(value: any): any {
  return value
}
/*
  以上就是一个最好的例子， ts为了有数据校验这一个功能，  如果我们在不确定类型的时候，  一样的一段代码就不得不以重载的方法重写很多遍
    这个是很不好的
    当我们如果形参返回值如果设置为 any 类型的话就解决了这个问题  但是却又缺失了类型检测这个功能  
      所以在这样的情况下  就可以使用泛型
*/

function getInfoT<T>(value: T): T {
  return value
}

console.log(getInfoT('aaa')) // aaa
console.log(getInfoT(59784)) //  59784 这样就实现了泛型  既有类型检测  又能自动匹配数据类型

// 泛型类

class addFun {
  public listArr: number[] = []
  add(n: number): void {
    this.listArr.push(n)
  }
  getMin(): number {
    let min = this.listArr[0]
    for (let i = 1; i < this.listArr.length; i++) {
      if (min > this.listArr[i]) {
        min = this.listArr[i]
      }
    }
    return min
  }
}
let numarr = new addFun()
numarr.add(87)
numarr.add(78)
numarr.add(345)
numarr.add(98)
console.log(numarr.getMin()) //  78
/*
  由以上的一个例子我们可以看出  我们写的这个类是只能使用于 number 类型的数组的
    其他类型是不能使用的  如 string类型是不能使用的   

    如果要使用 就必须得重新写一遍一模一样的代码 只是将约束的类型改成了  string类型而已  那如果是这样 代码的耦合度就非常高了   写的不够优雅
  所以为了解决这个问题  就可以使用 来约束类 简称泛型类
*/

// 泛型类
class newadd<T> {
  public listArr: T[] = []
  add(n: T): void {
    this.listArr.push(n)
  }
  getMin(): T {
    //  字符串比大小是通过比较 ASCII 值
    let min = this.listArr[0]
    for (let i = 1; i < this.listArr.length; i++) {
      if (min > this.listArr[i]) {
        min = this.listArr[i]
      }
    }
    return min
  }
}

let numberarr = new newadd()
numarr.add(87)
numarr.add(78)
numarr.add(345)
numarr.add(98)
console.log(numarr.getMin()) // 78

let stringarr = new newadd<string>()
stringarr.add('c')
// stringarr.add(4)  // 此处就会报错  因为类型检测不一致
stringarr.add('d')
console.log(stringarr.getMin()) // c

/*
  综上所述  在使用了泛型之后  我们一方面可以减少代码的耦合程度，  另外一方面还保留了代码量的少和优雅性   是最折中的一次使用了
    泛型还是非常重要的   在c#  java  中都是有泛型的
*/
